package com.xiaomazi.ucenter.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.xiaomazi.common.utils.JwtUtils;
import com.xiaomazi.common.utils.MD5;
import com.xiaomazi.common.utils.R;
import com.xiaomazi.servicebase.entity.UserInfo;
import com.xiaomazi.servicebase.entity.UserInfoToOrder;
import com.xiaomazi.servicebase.exception.LLXYException;
import com.xiaomazi.ucenter.dto.LoginDTO;
import com.xiaomazi.ucenter.dto.RegisterDTO;
import com.xiaomazi.ucenter.utils.HttpClientUtils;
import com.xiaomazi.ucenter.utils.WechatInfo;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaomazi.ucenter.mapper.UcenterMapper;
import com.xiaomazi.ucenter.entity.Ucenter;
import com.xiaomazi.ucenter.service.UcenterService;

import javax.servlet.http.HttpServletRequest;
import java.net.URLEncoder;
import java.util.Map;

@Service
public class UcenterServiceImpl extends ServiceImpl<UcenterMapper, Ucenter> implements UcenterService{

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private WechatInfo wechatInfo;

    /**
     * 注册用户的方法
     * @param registerDTO
     */
    @Override
    public R register(RegisterDTO registerDTO) {
        if (null == registerDTO){
            throw new LLXYException(20001,"请正确输入");
        }
        String code = registerDTO.getCode(); //验证码
        String mobile = registerDTO.getMobile(); //手机号
        String nickname = registerDTO.getNickname(); //昵称
        String password = registerDTO.getPassword(); //密码

        if(StrUtil.isBlank(mobile) || StrUtil.isBlank(password)
                || StrUtil.isBlank(code) || StrUtil.isBlank(nickname)) {
            throw new LLXYException(20001,"请正确输入");
        }

        String reallyCode = redisTemplate.opsForValue().get(mobile);
        if (StrUtil.isBlank(reallyCode) || !reallyCode.equals(code)){
            throw new LLXYException(20001,"验证码错误");
        }

        Long count = this.query().eq("mobile", mobile).count();
        if (count > 0){
            throw new LLXYException(20001,"该手机号已经被注册");
        }
        Ucenter ucenter = new Ucenter();
        ucenter.setMobile(mobile);
        ucenter.setNickname(nickname);
        ucenter.setPassword(MD5.encrypt(password));
        ucenter.setAvatar("https://llxy-bucket.oss-cn-nanjing.aliyuncs.com/2023/02/14/c6883aa622854fe0a41aa16f0879a389teacherFileAvatar.png");
        this.save(ucenter);
        return R.ok();
    }

    /**
     * 生成微信二维码
     * @return 地址
     */
    @Override
    public String generateWechatCode() {
        try {
            // 微信开放平台授权baseUrl  %s相当于?代表占位符
            String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
                    "?appid=%s" +
                    "&redirect_uri=%s" +
                    "&response_type=code" +
                    "&scope=snsapi_login" +
                    "&state=%s" +
                    "#wechat_redirect";
            String redirectUrl = wechatInfo.getRedirectUrl();
            redirectUrl = URLEncoder.encode(redirectUrl, "utf-8");
            //设置%s里面值
            String url = String.format(
                    baseUrl,
                    wechatInfo.getAppId(),
                    redirectUrl,
                    "xiaomazi"
            );
            return url;
        }catch(Exception e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
    }

    /**
     * 获取扫描人信息，添加数据
     * @param code  临时票据，类似于验证码
     * @param state 自定义的参数
     * @return
     */
    @Override
    public String getWechatUserInfo(String code, String state) {
        try {
            //拿着code临时票据去请求微信固定的地址，得到两个值 access_token 和 openid
            String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
                    "?appid=%s" +
                    "&secret=%s" +
                    "&code=%s" +
                    "&grant_type=authorization_code";
            //拼接三个参数 ：id  秘钥 和 code值
            String accessTokenUrl = String.format(
                    baseAccessTokenUrl,
                    wechatInfo.getAppId(),
                    wechatInfo.getAppSecret(),
                    code
            );
            //请求这个拼接好的地址，得到返回两个值 accsess_token 和 openid
            //使用httpclient发送请求，得到返回结果
            String accessTokenAndOpenIdStr = HttpClientUtils.get(accessTokenUrl);
            //从accessTokenAndOpenIdStr字符串获取出来两个值 accsess_token 和 openid
            //把accessTokenAndOpenIdStr字符串转换map集合，根据map里面key获取对应值
            JSONObject jsonObject = new JSONObject(accessTokenAndOpenIdStr);
            Map map = jsonObject.toBean(Map.class);
            if (jsonObject.isNull("access_token") || jsonObject.isNull("openid")) {
                throw new RuntimeException("转换异常");
            }
            String access_token = (String) map.get("access_token");
            String openid = (String) map.get("openid");
            //把扫描人信息添加数据库里面
            //判断数据表里面是否存在相同微信信息，根据openid判断
            Ucenter ucenter = this.query().eq("openid", openid).one();
            if (null == ucenter){
                String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                        "?access_token=%s" +
                        "&openid=%s";
                //拼接两个参数
                String userInfoUrl = String.format(
                        baseUserInfoUrl,
                        access_token,
                        openid
                );
                String userInfoStr = HttpClientUtils.get(userInfoUrl);
                JSONObject object = new JSONObject(userInfoStr);
                if (!object.isNull("nickname") && !object.isNull("headimgurl")){
                    ucenter = new Ucenter();
                    ucenter.setOpenid(openid);
                    ucenter.setNickname(object.get("nickname",String.class));
                    ucenter.setAvatar(object.get("headimgurl",String.class));
                    this.save(ucenter);
                }
            }
            String authentication = JwtUtils.getJwtToken(ucenter.getId(), ucenter.getNickname());
            return authentication;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据userId获取用户基本信息
     * @param userId id
     * @return userInfo
     */
    @Override
    public UserInfo getUserInfoByUserId(String userId) {
        Ucenter user = this.getById(userId);
        UserInfo userInfo = new UserInfo();
        userInfo.setMemberId(user.getId());
        userInfo.setNickname(user.getNickname());
        userInfo.setAvatar(user.getAvatar());
        return userInfo;
    }

    /**
     * 根据userId查询出用户基本信息 供生成订单调用
     * @param userId 用户id
     * @return UserInfoToOrder
     */
    @Override
    public UserInfoToOrder getUserInfoToOrderByUserId(String userId) {
        Ucenter user = this.getById(userId);
        UserInfoToOrder userInfoToOrder = new UserInfoToOrder();
        userInfoToOrder.setMemberId(user.getId());
        userInfoToOrder.setNickname(user.getNickname());
        userInfoToOrder.setMobile(user.getMobile());
        return userInfoToOrder;
    }

    /**
     * 根据日期查询出某一天的注册人数
     * @param day
     * @return
     */
    @Override
    public Integer getCountByDay(String day) {
        return baseMapper.countRegisterDay(day);
    }

    /**
     * 用户登录的方法
     * @param loginDTO 前端输入的用户名和密码
     * @return jwt-token
     */
    @Override
    public R login(LoginDTO loginDTO) {
        if (null == loginDTO || StrUtil.isBlank(loginDTO.getMobile()) || StrUtil.isBlank(loginDTO.getPassword())){
            throw new LLXYException(20001,"用户名和密码不能为空~");
        }
        String mobile = loginDTO.getMobile();
        String password = MD5.encrypt(loginDTO.getPassword());
        Ucenter ucenter = this.query().eq("mobile", mobile).one();
        if (null == ucenter){
            throw new LLXYException(20001,"用户名不存在");
        }
        if (ucenter.getIsDisabled()){
            throw new LLXYException(20001,"用户名已被永久封禁，请联系管理员");
        }
        if (!ucenter.getPassword().equals(password)){
            throw new LLXYException(20001,"密码错误");
        }

        String token = JwtUtils.getJwtToken(ucenter.getId(), ucenter.getNickname());
        return R.ok().data("authentication",token);
    }
}
